package com.thd.example.controller;

import com.thd.framework.basic.constants.CommonConstants;
import com.thd.framework.basic.model.Message;
import com.thd.framework.cache.utils.RedissonUtil;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.concurrent.TimeUnit;

@Controller
@RequestMapping("/componentTest")
public class ComponentTestController {
    @Autowired
    private RedissonClient redissonClient;
    @ResponseBody
    @RequestMapping("/testRedisson")
    public Message<String> testRedisson(){
        RedissonUtil.getMap("ttt").put("a","b");
        Object b = RedissonUtil.getMap("ttt").get("a");
        return Message.success(b);
    }



    // 测试并发锁 - 锁的标准写法
    // url : http://127.0.0.1:8010/componentTest/testStandardConcurrentLock
    // 一般情况下使用redisson锁的写法
    @GetMapping("/testStandardConcurrentLock")
    @ResponseBody
    public ResponseEntity testStandardConcurrentLock() {
        RLock lock = redissonClient.getLock("MYLOCK");
        try{
            // tryLock必须放在try中,因为如果等锁时间超时会抛出异常
            /**
             * tryLock
             * 第一个参数:等待时间,再此时间范围内会不断尝试获取锁,等待10S,
             超时返回false,
             在此期间获取到锁返回true
             * 第二个参数:锁的持有时间(超时自动释放)
             -1为不自动释放且会续租,
             除非手工释放锁或线程销毁(线程销毁会自动释放锁)
             * 第三个参数:上面2个参数的时间单位
             */
            boolean b = lock.tryLock(10,-1, TimeUnit.SECONDS);

            if(b){
                System.out.println(Thread.currentThread().getName() + "上锁 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                // =================== 以下是业务代码 =========================//
                try {
                    // 睡3S
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(Thread.currentThread().getName() + "离开 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                return ResponseEntity.ok("SUCCESS");
                // =================== 以上是业务代码 =========================//
            }else{
                System.out.println(Thread.currentThread().getName() + "超时 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                return ResponseEntity.status(500).body("超时");
            }
        }catch(InterruptedException e){
            System.out.println(Thread.currentThread().getName() + "被打断 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            return ResponseEntity.status(500).body("被打断");
        }finally {
            try{ // 用try是因为释放锁的时候必须是该线程上的锁,如果锁超期提前释放了,这里释放锁将会抛出异常
                lock.unlock();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}
